/*
 * @Author: LVGRAPE
 * @LastEditors: LVGRAPE
 */
#include "drv_serial.h"
#include <string.h>
#include <stdbool.h>
#include "drv_pin.h"
#include "drv_led.h"

#define USART1_TX_BUFFER_SIZE 256
#define USART1_RX_BUFFER_SIZE 256

struct rt_semaphore rx1_sem;

uint16_t tx1_size;
volatile bool tx1_busy = 0;

uint8_t usart1_tx_buffer[USART1_TX_BUFFER_SIZE]; // DMA, ringbuffer 共用缓冲。 DMA 读出，ringbuffer 写入
uint8_t usart1_rx_buffer[USART1_RX_BUFFER_SIZE]; // DMA, ringbuffer 共用缓冲。 DMA 写入，ringbuffer 读出
struct rt_ringbuffer rx1_ringbuffer = {
    .buffer_ptr = usart1_rx_buffer,
    .read_mirror = 0,
    .read_index = 0,
    .read_mirror = 0,
    .write_index = 0,
    .buffer_size = USART1_RX_BUFFER_SIZE};
struct rt_ringbuffer tx1_ringbuffer = {
    .buffer_ptr = usart1_tx_buffer,
    .read_mirror = 0,
    .read_index = 0,
    .write_mirror = 0,
    .write_index = 0,
    .buffer_size = USART1_TX_BUFFER_SIZE};

/**
 * @brief 计算缓冲区中没有发送的数据，如果缓冲区中有数据，则启动DMA发送
 *
 * @return int
 */
int tx1_send_buffer(void)
{
    if (tx1_ringbuffer.read_index <= tx1_ringbuffer.write_index)
    {
        /**缓冲未满，全部发送 */
        /** |---------Read----[data]-----Write-----------| */
        tx1_size = tx1_ringbuffer.write_index - tx1_ringbuffer.read_index;
    }
    else
    {
        /**缓冲已满，先发一部分，DMA中断接手剩余部分 */
        /**发送完成后，Read就回到Write左边了，也就是未满状态！环形缓冲转起来了！*/
        /** |----[data]-----Write-----Read----[data]-----| */
        tx1_size = tx1_ringbuffer.buffer_size - tx1_ringbuffer.read_index;
    }
    if (tx1_size > 0)
    {
        /**DMA发送 */
        tx1_busy = 1;
        DMA1_CHANNEL4->maddr = (uint32_t)tx1_ringbuffer.buffer_ptr + tx1_ringbuffer.read_index; // start address + read index
        DMA1_CHANNEL4->dtcnt = tx1_size;
        dma_channel_enable(DMA1_CHANNEL4, TRUE);
    }
    return tx1_size;
}
/**
 * @brief  把数据写入到缓冲区，如果DMA没有在忙，则启动DMA发送，
 * DMA会连续在发送，直到缓冲区为空
 *
 * @param buf
 * @param size
 * @return int
 */
int uart1_write(uint8_t *buf, rt_size_t size)
{
    // if (tx1_ringbuffer.write_mirror != tx1_ringbuffer.read_mirror)
    // {
    //     if (tx1_ringbuffer.write_index + size > tx1_ringbuffer.read_index) // buffer overflow
    //     {
    //         while (tx1_busy) // wait for DMA to send data
    //         {
    //             // rt_thread_delay(1);
    //         }
    //     }
    // }
    int space = rt_ringbuffer_space_len(&tx1_ringbuffer);
    while (space < size) // 等待缓冲区有足够的空间
    {
        if (!tx1_busy)
        {
            return tx1_send_buffer();
        }
    }

    /**先把数据写入到缓冲区 */
    rt_ringbuffer_put(&tx1_ringbuffer, buf, size);
    /**如果DMA没有在忙，则启动DMA发送 */
    if (!tx1_busy)
    {
        return tx1_send_buffer();
    }
    return 0;
}
/**
 * @brief  从缓冲区中读取数据
 *
 * @param buf
 * @param size
 * @return int
 */
int uart1_read(uint8_t *buf, rt_size_t size)
{
    return rt_ringbuffer_get(&rx1_ringbuffer, buf, size);
}
/**
 * @brief 缓冲区中有多少数据未读取
 *
 * @return int16_t
 */
int16_t usart1_get_rx_data_len(void)
{
    return rt_ringbuffer_data_len(&rx1_ringbuffer);
}

/**
 * @brief  DMA发送完成中断。
 * @param  none
 * @retval none
 */
void DMA1_Channel4_IRQHandler(void)
{
    rt_enter_critical();
    if (dma_interrupt_flag_get(DMA1_FDT4_FLAG))
    {
        tx1_busy = 0;
        dma_flag_clear(DMA1_FDT4_FLAG);
        dma_channel_enable(DMA1_CHANNEL4, FALSE);
        tx1_ringbuffer.read_index += tx1_size;
        if (tx1_ringbuffer.read_index >= tx1_ringbuffer.buffer_size)
        {
            // 下一圈
            tx1_ringbuffer.read_mirror = ~tx1_ringbuffer.read_mirror;
            // tx1_ringbuffer.read_index -= tx1_ringbuffer.buffer_size;
            tx1_ringbuffer.read_index = 0;
        }
        /**NOTE 如果缓冲区中还有数据，继续发送 */
        tx1_send_buffer();
    }
    rt_exit_critical();
}

/**
 * @brief  DMA接收完成中断
 * @param  none
 * @retval none
 */
void DMA1_Channel5_IRQHandler(void)
{
    rt_enter_critical();
    if (dma_interrupt_flag_get(DMA1_FDT5_FLAG))
    {
        dma_flag_clear(DMA1_FDT5_FLAG);
        dma_channel_enable(DMA1_CHANNEL5, false);
        /**NOTE DMA不重置的话，计数就不会重置，接收内存地址也会继续增加 */
        /**NOTE DMA传输完成中断，说明缓冲已满，从头开始 */
        rx1_ringbuffer.write_index = 0;
        rx1_ringbuffer.write_mirror = ~rx1_ringbuffer.write_mirror;
        /**NOTE 重新接收 */
        DMA1_CHANNEL5->maddr = (uint32_t)usart1_rx_buffer;
        dma_data_number_set(DMA1_CHANNEL5, USART1_RX_BUFFER_SIZE);
        dma_channel_enable(DMA1_CHANNEL5, true);
    }
    rt_exit_critical();
}
/**
 * @brief  USART1 空闲中断，主要是为了避免DMA完全接收完的时间太久，
 * 所以使用空闲中断来及时更新接收到的数据长度
 *
 */
void USART1_IRQHandler(void)
{
    rt_enter_critical();
    if (usart_interrupt_flag_get(USART1, USART_IDLEF_FLAG))
    {

        usart_flag_clear(USART1, USART_IDLEF_FLAG);
        usart_data_receive(USART1);
        /**NOTE 使用IDLE中断来更新接收到的数据长度 */
        /**NOTE DMA向下计数，剩余多少即是接收了多少 */
        /**NOTE DMA完成中断会必须要优先于空闲中断，并先将DMA计数重置 */
        /**NOTE |MAX------[DATA]---DMA_CNT-------0| */
        /**NOTE |0--------[DATA]---Write-------MAX| */
        uint16_t rxCnt = USART1_RX_BUFFER_SIZE - dma_data_number_get(DMA1_CHANNEL5);
        rx1_ringbuffer.write_index = rxCnt;

        // rt_kprintf("rx1_ringbuffer.write_index:%d\n", rx1_ringbuffer.write_index);
        rt_sem_release(&rx1_sem);
    }
    rt_exit_critical();
}

/**
 * @brief  config usart
 * @param  none
 * @retval none
 */
void usart_configuration(void)
{
    gpio_init_type gpio_init_struct;

    /* enable the usart1 and gpio clock */
    crm_periph_clock_enable(CRM_USART1_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);

    gpio_default_para_init(&gpio_init_struct);
    /* configure the usart2 tx pin */
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
    gpio_init_struct.gpio_pins = GPIO_PINS_9;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(GPIOA, &gpio_init_struct);

    /* configure the usart2 rx pin */
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
    gpio_init_struct.gpio_pins = GPIO_PINS_10;
    gpio_init_struct.gpio_pull = GPIO_PULL_UP;
    gpio_init(GPIOA, &gpio_init_struct);

    /* configure usart2 param */
    usart_init(USART1, 921600, USART_DATA_8BITS, USART_STOP_1_BIT);
    usart_transmitter_enable(USART1, TRUE);
    usart_receiver_enable(USART1, TRUE);
    usart_dma_transmitter_enable(USART1, TRUE);
    usart_dma_receiver_enable(USART1, TRUE);
    usart_interrupt_enable(USART1, USART_IDLE_INT, TRUE);
    nvic_irq_enable(USART1_IRQn, 1, 1);
    usart_enable(USART1, TRUE);
}

/**
 * @brief  config dma for usart2 and usart3
 * @param  none
 * @retval none
 */
void dma_configuration(void)
{
    dma_init_type dma_init_struct;

    /* enable dma1 clock */
    crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);

    /* dma1 channel1 for usart1 tx configuration */
    dma_reset(DMA1_CHANNEL4);
    dma_default_para_init(&dma_init_struct);
    dma_init_struct.buffer_size = USART1_TX_BUFFER_SIZE;
    dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;
    dma_init_struct.memory_base_addr = (uint32_t)usart1_tx_buffer;
    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
    dma_init_struct.memory_inc_enable = TRUE;
    dma_init_struct.peripheral_base_addr = (uint32_t)&USART1->dt;
    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
    dma_init_struct.peripheral_inc_enable = FALSE;
    dma_init_struct.priority = DMA_PRIORITY_MEDIUM;
    dma_init_struct.loop_mode_enable = FALSE;
    dma_init(DMA1_CHANNEL4, &dma_init_struct);

    /* enable transfer full data interrupt */
    dma_interrupt_enable(DMA1_CHANNEL4, DMA_FDT_INT, TRUE);

    /* dma1 channel1 interrupt nvic init */
    nvic_irq_enable(DMA1_Channel4_IRQn, 0, 0);

    /* config flexible dma for usart2 tx */
    // dma_flexible_config(DMA1, FLEX_CHANNEL1, DMA_FLEXIBLE_UART1_TX);

    /* dma1 channel3 for usart1 rx configuration */
    dma_reset(DMA1_CHANNEL5);
    dma_default_para_init(&dma_init_struct);
    dma_init_struct.buffer_size = USART1_RX_BUFFER_SIZE;
    dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
    dma_init_struct.memory_base_addr = (uint32_t)usart1_rx_buffer;
    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
    dma_init_struct.memory_inc_enable = TRUE;
    dma_init_struct.peripheral_base_addr = (uint32_t)&USART1->dt;
    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
    dma_init_struct.peripheral_inc_enable = FALSE;
    dma_init_struct.priority = DMA_PRIORITY_MEDIUM;
    dma_init_struct.loop_mode_enable = FALSE;
    dma_init(DMA1_CHANNEL5, &dma_init_struct);

    /* enable transfer full data interrupt */
    dma_interrupt_enable(DMA1_CHANNEL5, DMA_FDT_INT, TRUE);

    /* dma1 channel3 interrupt nvic init */
    nvic_irq_enable(DMA1_Channel5_IRQn, 0, 0);

    /* config flexible dma for usart2 rx */
    // dma_flexible_config(DMA1, FLEX_CHANNEL3, DMA_FLEXIBLE_UART1_RX);

    dma_channel_enable(DMA1_CHANNEL5, TRUE); /* usart1 rx begin dma receiving */
}
void rt_hw_uart1_init(void)
{

    usart_configuration();
    dma_configuration();
    rt_sem_init(&rx1_sem, "rx1_sem", 10, 0);
    // led_pins_init();
}
int rt_hw_console_init(void)
{
    rt_hw_uart1_init();
    return 0;
}

void rt_hw_console_output(const char *str)
{
    uint16_t len = rt_strlen(str);
    // while(tx1_busy);
    uart1_write((uint8_t *)str, len);
}
void rt_hw_console_output_data(uint8_t *dat, uint16_t len)
{
    uart1_write(dat, len);
}
int rt_hw_console_getchar(void)
{
    rt_uint8_t ch = -1;
    while (rt_ringbuffer_getchar(&rx1_ringbuffer, &ch) != 1)
        rt_sem_take(&rx1_sem, RT_WAITING_FOREVER);
    return (int)ch;

    // if (rt_ringbuffer_getchar(&rx1_ringbuffer, &ch) == 1)
    //     return (int)ch;
    // return -1;
}
